package com.ww.juc.futureandcallable;

import com.google.common.util.concurrent.*;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GuavaFutureDemo {

    public static final int SLEEP_GAP = 500;
    
    private static Logger log = LoggerFactory.getLogger(GuavaFutureDemo.class);

    public static String getCurThreadName() {
        return Thread.currentThread().getName();
    }

    static class HotWarterJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            try {
                log.info("洗好水壶");
                log.info("灌上凉水");
                log.info("放在火上");
                // 烧水中...
                Thread.sleep(SLEEP_GAP);
            } catch (InterruptedException e) {
                log.info("发生异常中断了");
                return false;
            }

            log.info("水已烧开");
            return true;
        }
    }

    static class WashJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            try {
                log.info("洗茶壶");
                log.info("洗茶杯");
                log.info("拿茶叶");
                // 洗水壶中
                Thread.sleep(SLEEP_GAP);
//                throw new RuntimeException("手动抛异常了");
                log.info("洗完了");
            } catch (InterruptedException e) {
                log.info("清洗工作中断了");
                return false;
            }
            log.info("清洗工作已完成");
            return true;
        }
    }

    static class MainJob implements Runnable {

        boolean warterOk = false;
        boolean cupOk = false;
        int gap = SLEEP_GAP / 10;

        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(gap);
                    log.info("读书中...");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                if (warterOk && cupOk) {
                    drinkTea(warterOk, cupOk);
                }
            }
        }

        public void drinkTea(Boolean wOk, Boolean cOk) {
            if (wOk && cOk) {
                log.info("泡茶喝、茶喝完");
                warterOk = false;
                gap = SLEEP_GAP * 100;
            } else if (!wOk) {
                log.info("烧水失败，没茶喝了");
            } else if (!cOk) {
                log.info("杯子没洗，喝不了茶");
            }
        }
    }

    public static void main(String[] args) {
        MainJob mainJob = new MainJob();
        Thread mainThread = new Thread(mainJob);
        mainThread.setName("主线程");
        mainThread.start();

        Callable<Boolean> hotWarterJob = new HotWarterJob();
        Callable<Boolean> washJob = new WashJob();

        // Java线程池
        ExecutorService jPool = Executors.newFixedThreadPool(10);
        // Guava线程池
        ListeningExecutorService gPool = MoreExecutors.listeningDecorator(jPool);
        ListenableFuture<Boolean> hotFuture = gPool.submit(hotWarterJob);
        Futures.addCallback(hotFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                if (result) {
                    mainJob.warterOk = true;
                }
            }

            @Override
            public void onFailure(Throwable t) {
                log.info("烧水失败，没有茶喝了");
            }
        }, gPool);

        ListenableFuture<Boolean> washFuture = gPool.submit(washJob);
        Futures.addCallback(washFuture, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean result) {
                if (result) {
                    mainJob.cupOk = true;
                }
            }

            @Override
            public void onFailure(Throwable t) {
                log.info("杯子没洗好，喝不了水");
            }
        }, gPool);
    }
}
